#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <cstring>
#include <fcntl.h>
 
constexpr int BUFFER_SIZE = 1024;
 
int main()
{
    // 创建一个共享内存对象
    /**
     * int shm_open (const char *__name, int __oflag, mode_t __mode);
     */
    char shm_name[256] = {0};
    std::sprintf(shm_name, "letter %d", getpid());
    int fd = shm_open(shm_name, O_RDWR | O_CREAT, 0644);
    if (fd == -1)
    {
        perror("shm_open");
        std::exit(EXIT_FAILURE);
    }
    // 设置共享内存对象的大小
    ftruncate(fd, BUFFER_SIZE);
    // 映射共享内存对象
    char *share = static_cast<char*>(mmap(nullptr, BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
    if (share == MAP_FAILED)
    {
        perror("mmap");
        std::exit(EXIT_FAILURE);
    }
    // 映射完成后关闭文件描述符
    close(fd);
    // 使用内存映射实现进程间通讯
    pid_t pid = fork();
    if (pid == -1)
    {
        perror("fork");
        std::exit(EXIT_FAILURE);
    }
    if (pid == 0)
    {
        // 子进程
        std::strcpy(share, "你好，父进程，我是子进程\n");
        std::cout << "子进程 " << getpid() << " 写入数据, 并且发送成功" << std::endl;
    }
    else
    {
        // 父进程
        waitpid(pid, nullptr, 0);
        std::cout << "父进程 " << getpid() << " 收到子进程 " << pid << " 的回复: " << share << std::endl;
        // 释放映射区
        int re = munmap(share, BUFFER_SIZE);
        if (re == -1)
        {
            perror("munmap");
            std::exit(EXIT_FAILURE);
        }
    }
 
    // 释放共享内存对象 也就是对文件操作符操作 引用计数减一
    shm_unlink(shm_name);
    return 0;
}